/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

package cuatroenraya;
import cuatroenraya.gui.JugadorGUIHandler;

/**
 *
 * @author mateo
 */
public class Arbitro {

    protected int cantFichas;

        public Arbitro(int cantF)
    {
        cantFichas = cantF;
    }

        // Arranca el partido entre dos jugadores.
    public int EmpezarPartido(Jugador a, Jugador b)
    {
      int[][] tablero = new int [8][8];
      int[][] tableroParam = new int [8][8];
      Jugador jugadorActual;
      int usarFicha;
      Jugador proxJugador;
      int[] jugada;
      int cantJugadas=0;
      // Inicializar jugadorActual aleatoriamente
      a.setNumeroJugador(1);
      b.setNumeroJugador(2);
      jugadorActual = a;

      do
      {
        if(cantJugadas==640) return 0; //Empate
        jugada = jugadorActual.jugar(tableroParam);
        // Validar que no se intente poner una ficha donde hay otra y que la jugada no esté fuera de rango.
        // Si ya hubiera una, poner la nueva en un lugar vacio aleatorio o en la primera que se encuentre vacia

        if(jugadorActual.equals(a))
        {
            usarFicha = 1;
            a.setNumeroJugador(usarFicha);
            proxJugador = b;
        }
        else
        {
            usarFicha = 2;
            b.setNumeroJugador(usarFicha);
            proxJugador = a;
        }

        if (controlarJugadaCorrecta(tablero, jugadorActual, jugada, cantFichas, cantJugadas, usarFicha ))
        {
            tablero[jugada[2]][jugada[3]] = usarFicha;
            if(cantFichas <= (cantJugadas)/2)
            {
                tablero[jugada[0]][jugada[1]] = 0;
            }
        }
        else //Si no es correcta la jugada...
        {
            int [] jugadaAlternativa = new int[4];
            if(cantFichas <= (cantJugadas)/2)
             {
                 jugadaAlternativa = devolverJugadaPosible(tablero, usarFicha);
                 tablero[jugadaAlternativa[0]][jugadaAlternativa[1]] = 0;
             }
             else
             {
                 jugadaAlternativa = devolverPrimerVacio(tablero);
             }
             tablero[jugadaAlternativa[2]][jugadaAlternativa[3]] = usarFicha;
             jugada = jugadaAlternativa;
        }
        jugadorActual = proxJugador;
        if(jugadorActual.equals(a) && !(jugadorActual instanceof JugadorGUIHandler))
        {
            tableroParam = girarTablero(tablero);
        }
        else
        {
            tableroParam = copiarTablero(tablero);
        }
        cantJugadas++;
      }while(!controlarJugadaGanadora(tablero, a, jugada));

      // Antes de salir, si algun jugador es gui, mostrar el tablero.
      if(a instanceof JugadorGUIHandler)
      {
          ((JugadorGUIHandler)a).mostrarTablero(tablero);
      } else if(b instanceof JugadorGUIHandler)
      {
         ((JugadorGUIHandler)b).mostrarTablero(tablero);
      }

      return usarFicha;
    }

    // Arranca el partido entre dos jugadores.
    public int EmpezarPartido(Jugador a, Jugador b, JugadorGUIHandler jt)
    {
      int[][] tablero = new int [8][8];
      int[][] tableroParam = new int [8][8];
      Jugador jugadorActual;
      int usarFicha;
      Jugador proxJugador;
      int[] jugada;
      int cantJugadas=0;
//      int cantFichas=5;
      jt.ShowPanel(tablero);
      // Inicializar jugadorActual aleatoriamente
      jugadorActual = a;
      a.setNumeroJugador(1);
      b.setNumeroJugador(2);

      do
      {
        if(cantJugadas==640) return 0; //Empate
        jugada = jugadorActual.jugar(tableroParam);
        // Validar que no se intente poner una ficha donde hay otra y que la jugada no esté fuera de rango.
        // Si ya hubiera una, poner la nueva en un lugar vacio aleatorio o en la primera que se encuentre vacia

        if(jugadorActual.equals(a))
        {
            usarFicha = 1;
            a.setNumeroJugador(usarFicha);
            proxJugador = b;
        }
        else
        {
            usarFicha = 2;
            b.setNumeroJugador(usarFicha);
            proxJugador = a;
        }

        if (controlarJugadaCorrecta(tablero, jugadorActual, jugada, cantFichas, cantJugadas, usarFicha ))
        {
            tablero[jugada[2]][jugada[3]] = usarFicha;
            if(cantFichas <= cantJugadas/2)
            {
                tablero[jugada[0]][jugada[1]] = 0;
            }
        }
        else //Si no es correcta la jugada...
        {
            int [] jugadaAlternativa = new int[4];
            if(cantFichas <= cantJugadas/2)
             {
                 jugadaAlternativa = devolverJugadaPosible(tablero, usarFicha);
                 tablero[jugadaAlternativa[0]][jugadaAlternativa[1]] = 0;
             }
             else
             {
                 jugadaAlternativa = devolverPrimerVacio(tablero);
             }
             tablero[jugadaAlternativa[2]][jugadaAlternativa[3]] = usarFicha;
             jugada = jugadaAlternativa;
        }
        jt.ShowPanel(tablero);
        jugadorActual = proxJugador;
        if(jugadorActual.equals(a) && !(jugadorActual instanceof JugadorGUIHandler))
        {
            tableroParam = girarTablero(tablero);
        }
        else
        {
            tableroParam = copiarTablero(tablero);
        }
        cantJugadas++;
      }while(!controlarJugadaGanadora(tablero, a, jugada));

      return usarFicha;
    }

    //Cambiar en al tablero los unos por los dos y los dos por los unos
    private int[][] girarTablero(int[][] tablero)
    {
       int[][] tableroNuevo = new int [8][8];
       for(int i = 0; i<8;  i++)
       {
           for(int j = 0; j<8;  j++)
           {
               if(tablero[i][j]==1)
               {
                   tableroNuevo[i][j]=2;
               }
               else
               {
                   if(tablero[i][j]==2)
                   {
                       tableroNuevo[i][j]=1;
                   }
                   else
                   {
                       tableroNuevo[i][j]=0;
                   }
               }
           }
       }
       return tableroNuevo;
    }

    private int[][] copiarTablero(int[][] tablero)
    {
       return tablero.clone();
    }


    // El tablero, el jugador que tiene que mover, la coordenada que quiere mover.
    private boolean controlarJugadaCorrecta(int[][] tablero, Jugador a, int[] jugada, int cantFichas, int cantJugadas, int usarFicha)
    {
        if(jugada[2]>=0 && jugada[2]<8 && jugada[3]>=0 && jugada[3]<8)
        {
            if(tablero[jugada[2]][jugada[3]]==0)
            {
                if(cantJugadas/2 < cantFichas)
                {
                    return true;
                }
                else
                {
                    if(jugada[0]>=0 && jugada[0]<8 && jugada[1]>=0 && jugada[1]<8)
                    {
                        if(tablero[jugada[0]][jugada[1]]==usarFicha)
                        {
                            if(Math.abs(jugada[0]-jugada[2]) < 2 && Math.abs(jugada[1]-jugada[3]) < 2)
                            {
                                return true;
                            }
                            else
                            {
                                return false;
                            }
                        }
                        else
                        {
                            return false;
                        }
                    }
                    else
                    {
                        return false;
                    }
                }
            }
            else
            {
                return false;
            }
        }
        else
        {
            return false;
        }
    }
    
    // El tablero, el jugador que tiene que mover, la coordenada que quiere mover.
    private boolean controlarJugadaGanadora(int[][] tablero, Jugador a, int[] jugada)
    {
        int vert = 0;
        int horiz = 0;
        int diag45 = 0;
        int diag135 = 0;
        int ficha = tablero[jugada[2]][jugada[3]];
        for(int i = 0; i<7;  i++) // for(i = jugada[3]-3; i<=jugada[3]+3;  i++)
        {   // Los if controlan que los subindices no se salgan de rango, el
            // resto se hace con los contadores de los "?"

            if(jugada[2]+i-3 < 8 && jugada[2]+i-3 >= 0)
            {
                vert = (tablero[jugada[2]+i-3][jugada[3]] == ficha) ? (vert + 1) : (0);
            }
            else
            {
                vert = 0;
            }
            if(jugada[3]+i-3 < 8 && jugada[3]+i-3 >=0)
            {
                horiz = (tablero[jugada[2]][jugada[3]+i-3] == ficha) ? (horiz + 1) : (0);
            }
            else
            {
                horiz = 0;
            }
            if(jugada[2]+i-3 < 8 && jugada[2]+i-3 >= 0 && jugada[3]+i-3 < 8 && jugada[3]+i-3 >=0)
            {
                diag45 = (tablero[jugada[2]+i-3][jugada[3]+i-3] == ficha) ? (diag45 + 1) : (0);
            }
            else
            {
                diag45 = 0;
            }
            if(jugada[2]-i+3 < 8 && jugada[2]-i+3 >= 0 && jugada[3]+i-3 < 8 && jugada[3]+i-3 >=0)
            {
                diag135 = (tablero[jugada[2]-i+3][jugada[3]+i-3] == ficha) ? (diag135 + 1) : (0);
            }
            else
            {
                diag135 = 0;
            }
            if(vert==4 || horiz==4 || diag45==4 || diag135==4) // Controla si algún contador llegó a 4 y termina
            {
                return true;
            }
        }
        return false;
    }
    private int[] devolverPrimerVacio(int[][] tablero)
    {
        int[] primerVacio = new int[4];
        for(int i=0; i<8; i++)
        {
            for(int j=0; j<8; j++)
            {
                if(tablero[i][j]==0)
                {
                    primerVacio[0]=0;
                    primerVacio[1]=0;
                    primerVacio[2]=i;
                    primerVacio[3]=j;
                    return primerVacio;
                }
            }
        }
        primerVacio[0]=9;
        primerVacio[1]=9;
        primerVacio[2]=9;
        primerVacio[3]=9;
        return primerVacio;
    }
    private int[] devolverJugadaPosible(int[][] tablero, int usarFicha)
    {
        int[] jugadaPosible = new int[4];
        for(int i=0; i<8; i++)
        {
            for(int j=0; j<8; j++)
            {
                if(tablero[i][j]==0)
                {
                    for(int ii=Math.max(i-1, 0); ii<Math.min(i+2, 8); ii++)
                    {
                        for(int jj=Math.max(j-1, 0); jj<Math.min(j+2, 8); jj++)
                        {
                            if(tablero[ii][jj]==usarFicha)
                            {
                                jugadaPosible[0]=ii;
                                jugadaPosible[1]=jj;
                                jugadaPosible[2]=i;
                                jugadaPosible[3]=j;
                                return jugadaPosible;
//                                JOptionPane.showMessageDialog(null,"Jugada posible: " + usarFicha + " Jugada: " + jugadaPosible[0] + " - " + jugadaPosible[1]);
                            }
                        }
                    }
                }
            }
        }
        jugadaPosible[0]=9;
        jugadaPosible[1]=9;
        jugadaPosible[2]=9;
        jugadaPosible[3]=9;
        return jugadaPosible;
    }
}

